package jp.oesf.rssreader;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import jp.oesf.rssreader.model.ChannelModel;
import jp.oesf.rssreader.model.ItemModel;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;

public class RssReader extends Activity {
    /** Called when the activity is first created. */
	Button readButton = null;
	private static final String TAG = "RssReader";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.main);
        //
		readButton = (Button)findViewById(R.id.button_read);
        
    }
    // 読み取りボタンクリック処理
    public void onClickReadButton(View view) {
    	//読み取り処理をバックグランドにて実行
    	Log.v(TAG,"onClickReadButton");
    	readButton.setEnabled(false);
    	//
    	new MyAsyncTask().execute("args as doInBackground");
    }
    // 一覧表示ボタンクリック処理
    public void onClickListButton(View view) {
    	// 一覧表示画面へ遷移
        Intent intent = new Intent(this, RssReaderList.class);
        //画面遷移実行
        startActivity(intent);
    }
    /*
     * 受信処理をスレッドにて実行する。
     * 		受信　→　解析　→　DB更新
     */
    class MyAsyncTask extends AsyncTask<String, Integer, Boolean>{
    	private List<ItemModel> itemModels = new ArrayList<ItemModel>();
    	private ChannelModel channelModel = new ChannelModel();

    	private static final String READ_OK = "読込み完了";	//正常終了時のトーストメッセージ
    	private static final String READ_NG = "読込み失敗";	//異常終了時のトーストメッセージ

    	//前処理
		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
			setProgressBarIndeterminateVisibility(true);

		}
    	//スレッド処理
		@Override
		protected Boolean doInBackground(String... arg0) {
			boolean ret = true;		//処理結果通知用
			//
			// TODO Auto-generated method stub
	        String url_para = "http://192.168.12.41:8080/files/oesf_rss.xml" ;
	        //接続先URLのコンテンツをInputStreamとして取得する。
	        InputStream in = getHtml( url_para );
	        
	        if (in != null){
	            //取得したXMLを解析し、記事を取得する。
	            ret = getparsed( in );
	            if (ret){
	                //取得記事を取得DBに書き込む。
	                writeDatabase();
	            }else{
	            	ret = false;
	            }
	        }else{
            	ret = false;        	
	        }
	        //処理中確認のため、ダミーウエイト
//			try {
//				Thread.sleep(10000);
//			} catch (InterruptedException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
			return ret;
		}
    	//後処理
		@Override
		protected void onPostExecute(Boolean result) {
			// TODO Auto-generated method stub
			super.onPostExecute(result);
	        //処理結果を表示する。
			String endMessage = null;
			if (result){
				endMessage = READ_OK;
			}else{
				endMessage = READ_NG;
			}
	        Toast.makeText(RssReader.this, endMessage, Toast.LENGTH_LONG).show();
	        //プログレスバーを消す
	        setProgressBarIndeterminateVisibility(false);
	        //読込みボタンを有効にする。
			readButton.setEnabled(true);
		}

		/*
	     * Httpのコンテンツをストリームとして返却する。
	     */
		private InputStream getHtml( String url )
		{
			InputStream content = null;
			
			// TODO 【HTTP通信①】No.01 DefaultHttpClientオブジェクトの生成する
			DefaultHttpClient client = new DefaultHttpClient();

			// GETメソッドで接続するリクエストオブジェクトの生成する
			HttpGet get = new HttpGet( url );

			try
			{	// リクエストを発行してレスポンスを取得する
				HttpResponse res = client.execute( get );

				//  ステータスコードのチェックする
				if( res.getStatusLine().getStatusCode() == HttpStatus.SC_OK )
				{	
					//コンテンツを取得
					content = getContents( res );
				}else {
					Log.e( TAG, "Http status NG: " );
				}
			}
			catch (Exception e)
			{	Log.e( TAG, Log.getStackTraceString(e));
			}
			return content;
		}
		/*
		 * Http のコンテンツを取得する。
		 */
		private InputStream getContents( HttpResponse res )
		{	InputStream in = null;
			// ByteArrayOutputStream out = null;

			try
			{	// レスポンスから InputStream を取得する
				in = res.getEntity().getContent();
			}
			catch( Exception e )
			{	Log.e( TAG, Log.getStackTraceString( e ));
			}
			return( in );
		} // getContents()

		private boolean getparsed( InputStream content ){
		
			InputStream is = content;
			boolean channel_fund = false;
			boolean channelUrl_fund = false;
			boolean ret = true;

			try {
				// 解析対象のストリームを取得する
				// XmlPullParserを定義する
				final XmlPullParser parser = Xml.newPullParser();			
				//  パースする文字列のストリームを渡す
				parser.setInput(new InputStreamReader(is));
				int eventType = 0;
				// XmlPullParser パースしている階層を取得
				final int depth = parser.getDepth();
				// XmlPullParser パースの終了条件
				while (((eventType = parser.next()) != XmlPullParser.END_DOCUMENT || parser
						.getDepth() > depth)) {
					// XmlPullParser eventTypeが開始タグか判定
					if (eventType == XmlPullParser.START_TAG) {
						// XmlPullParser タグの名前を取得する
						String tag = parser.getName();
						// title を社名に設定する名前を取得する
						if ("title".equals(tag) && (channel_fund == false)) {
							parser.next();
							channelModel.setChannel(parser.getText());
							channel_fund = true;
						}
						// link 会社URLに設定する名前を取得する
						if ("link".equals(tag) && (channelUrl_fund == false)) {
							parser.next();
							channelModel.setChannelUrl(parser.getText());
							channelUrl_fund = true;
						}
						// XmlPullParser タグの名前が"item"なら、parseToRowItemを呼び出す
						if ("item".equals(tag)) {
							// item を取得する
							ItemModel itemModel = parseToRowItem(parser);
							itemModels.add(itemModel);
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
				ret = false;
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			return ret;
		} // getparsed()
		/*
		 * Item 部の解析
		 */
		private ItemModel parseToRowItem(XmlPullParser parser) 
					throws XmlPullParserException, IOException {
			ItemModel itemModel = new ItemModel();
			int eventType;
			String tag = null;
			// パースする階層を取得する
			final int depth = parser.getDepth();
			// パースの終了条件
			while (((eventType = parser.next()) != XmlPullParser.END_DOCUMENT || parser
					.getDepth() > depth)) {
				// eventTypeが開始タグか判定
				if (eventType == XmlPullParser.START_TAG) {
					tag = parser.getName();
					// 
					if ("title".equals(tag)) {
						// 次に移動する。
						parser.next();
						// title取得し、itemModelのURLにセットする。
						itemModel.setTitle(parser.getText()); 

					} else if ("link".equals(tag)) {
						// 次に移動する。
						parser.next();
						// link取得し、itemModelにセットする。
						itemModel.setLink(parser.getText()); 
					} else if ("description".equals(tag)) {
						// 次に移動する
						parser.next();
						// descriptionを取得、itemModeにセットする。。
						itemModel.setDescription(parser.getText()); 
						
					} else if ("pubDate".equals(tag)) {
						// 次に移動する。
						parser.next();
						// pubDateを取得、itemModeにセットする。。
						itemModel.setPubDate(parser.getText()); 

					}else if ("category".equals(tag)) {
						// 次に移動する。
						parser.next();
						// categoryを取得、itemModeにセットする。。
						itemModel.setCategory(parser.getText()); 
					}
					// eventTypeが終了タグか判定
				} else if (eventType == XmlPullParser.END_TAG) {
					// タグの名前を取得する
					tag = parser.getName();
					// タグの名前が"entry"ならbreakする
					if ("item".equals(tag)) {
						break;
					}
				}
			}
			return itemModel;
		}
		/*
		 * 会社情報と記事情報をDBに書き込みます。
		 */
		private void writeDatabase(){
			long channelId = 0;			//
			long resultChannel;			//Channel用　sql実行結果
			long resultItem;			//Item用　sql実行結果 
			String[] channelPara = new String[1];	//Channel用　検索条件
			ContentValues contentValuesChannel = new ContentValues();	//Chanenel　SQL実行用　Value
			ContentValues contentValuesItem = new ContentValues();		//Item　SQL実行用　Value
			
			RssReaderSQLiteOpenHelper databaseOpenHelper = 
				new RssReaderSQLiteOpenHelper(RssReader.this);
			SQLiteDatabase database = databaseOpenHelper.getWritableDatabase();
			//会社がDBに存在するか確認する。
			channelPara[0] = channelModel.getChannel();

			//会社名が一致するＲＯＷ　の読込み
			Cursor cursorChannel = database.query(RssReaderSQLiteOpenHelper.CHANNEL_TABLE, 
					null, "channel=?", channelPara, null, null, null);
			Log.v(TAG, "Channel open = " + channelId );

			// 会社用Valueの設定
			contentValuesChannel.put("channel", channelModel.getChannel());
			contentValuesChannel.put("channelUrl", channelModel.getChannelUrl());

			if ((cursorChannel != null) && (cursorChannel.getCount() > 0)){
				//存在する場合は、会社のＩＤを取得する。
				startManagingCursor(cursorChannel);
				cursorChannel.moveToFirst();
				channelId = cursorChannel.getInt(cursorChannel.getColumnIndex("_id"));
				Log.v(TAG, "Channel found id = " + channelId );
				//更新処理
				resultChannel = database.update(RssReaderSQLiteOpenHelper.CHANNEL_TABLE, 
						contentValuesChannel, "_id="+channelId, null);
				Log.v("RSS READER", "Cannel Update Result= " + resultChannel);
			}else{
				//無い場合は、Insert
				resultChannel = database.insert(RssReaderSQLiteOpenHelper.CHANNEL_TABLE,
						null, contentValuesChannel);
				//Insetの場合、channelIdは、Insart時の返却値を設定
				channelId = resultChannel;
				Log.v("RSS READER", "Cannel Insert Result= " + resultChannel);
			}
			// カーソルのクローズ
			if (cursorChannel != null){
				cursorChannel.close();
			}
			//該当会社の記事を全て削除する。
			resultItem = database.delete(RssReaderSQLiteOpenHelper.ITEM_TABLE, "channelId=" + channelId , null);
			Log.v(TAG, "Item Delete Result= " + resultItem);
			
			// 記事情報の書き込み
			for (int i = 0 ; i < itemModels.size(); i++){
				//List　よりitemModelを取り出す。
				ItemModel itemModel = itemModels.get(i);
				//itemModel　より　ContentValues　に値を設定する。
				contentValuesItem.put("channelId", channelId);	//チャネルＩＤは、会社情報作成時の値を用いる
				contentValuesItem.put("title", itemModel.getTitle());
				contentValuesItem.put("link", itemModel.getLink());
				contentValuesItem.put("description", itemModel.getDescription());
				contentValuesItem.put("pubDate", itemModel.getPubDate());
				contentValuesItem.put("category", itemModel.getCategory());
				resultItem = database.insert(RssReaderSQLiteOpenHelper.ITEM_TABLE,
							null, contentValuesItem);
				Log.v(TAG, "Item Insrt Result= " + resultItem);
			}
			database.close();
			databaseOpenHelper.close();
		}
    	
    }

}